package adventure_game;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.Scanner;

/**
 * The Game class is the engine of Adventure Game.
 * @author Frank, Ronni & Morten B.
 */
public class Game
{
    private HashMap<String, Room> rooms;
    private Parser parser;
    private Room currentRoom;
    private ConfigReader reader = new ConfigReader("adventure.properties");
    private HashMap<String, Item> items;
    Item winningItem;
    private Player player;
    private ArrayList<Player> playersList = new ArrayList<Player>();

    /**
    * Starts the game. containing players, rooms and items.
    */
    public Game() throws IOException
    {
        rooms = new HashMap<String, Room>();
        items = new HashMap<String, Item>();
        createRooms();
        createItems();
        placeItems();
        addPlayers();
        parser = new Parser(new Scanner(System.in));
        player = playersList.get(0);

        winningItem = RandomItem();
    }

    /**
    * Creates items to place in rooms.
    */
    private void createItems() throws IOException
    {
        String value = reader.getProperty("items");
        String[] itemNames = value.split(",");
        for (String itemName : itemNames)
        {
            itemName = itemName.trim();
            Item i = new Item(itemName);
            items.put(itemName, i);
        }
    }

    /**
    * Creates the rooms and link them together.
    */
    private void createRooms() throws IOException
    {
        String value = reader.getProperty("rooms");
        String[] roomNames = value.split(",");
        for (String roomName : roomNames)
        {
            roomName = roomName.trim();
            Room r = new Room(roomName);
            rooms.put(roomName, r);
        }
 
        /**
        * Random start location
        */
        currentRoom = GetRandomRoom();

        /**
        * initialise room exits
        */
        String value2 = reader.getProperty("doors");
        String[] doors = value2.split(",");
        for (String door : doors)
        {
            String[] doorInfo = door.split("-");
            String roomName1 = doorInfo[0].trim();
            String direction = doorInfo[1].trim();
            String roomName2 = doorInfo[2].trim();
            Room room1 = rooms.get(roomName1);
            Room room2 = rooms.get(roomName2);
            room1.setExit(direction, room2);
        }
    }

    /**
    * Generates a random room.
    */    
    private Room GetRandomRoom()
    {
        int randomIdx = new Random().nextInt(rooms.size());
        return (Room) rooms.values().toArray()[randomIdx];
    }

    /**
    * Loops until game ends
    */
    public void play()
    {
        printWelcome();
        boolean finished = false;
        while (!finished)
        {
            System.out.print("> ");
            Command command = parser.getCommand();
            finished = processCommand(command);
        }
        System.out.println("Good bye!");
    }

    /**
    * Welcome screen txt
    */
    private void printWelcome()
    {
        System.out.println("Welcome to the our little AdventureGame v1.2.2 \n" +
                "Made by Frank, Ronni & Morten. \n" + "Type '" +
                CommandWord.HELP + "' if you need help. \n" +
                currentRoom.getShortDescription() + "\n" +
                "There is a secret item in this game, if you find it you win!");

    }

    /**
    * add command word
    */
    private boolean processCommand(Command command)
    {
        CommandWord commandWord = command.getCommandWord();
        if (commandWord == CommandWord.UNKNOWN)
        {
            System.out.println("Say what...???");
            return false;
        }
        if (commandWord == CommandWord.HELP)
        {
            printHelp();
            return false;
        }
        if (commandWord == CommandWord.TAKE)
        {
            Item x = pickUpItem(command);
            if (x != null)
            {
                player.addMove();
                if (x == winningItem)
                {
                    System.out.println("Congratulations " + player.getName() + " you've won the game!");
                    return true;
                }
            }

            return false;
        }
        if (commandWord == CommandWord.LOOK)
        {
            printLook();
            player.addMove();
            return false;
        }
        if (commandWord == CommandWord.IVENTORY)
        {
            printInventory();
            return false;
        }
        if (commandWord == CommandWord.DROP)
        {
            drop(command);
            player.addMove();
            return false;
        }
        if (commandWord == CommandWord.GO)
        {
            goRoom(command);
            player.addMove();
            return false;
        }
        if (commandWord == CommandWord.QUIT)
        {
            return true;
        }
        return false;
    }

    /**
     * Prints help!
     */
    private void printHelp()
    {
        System.out.println("Confused??? \n" + "This is your options:");
        parser.showCommands();
    }

    /**
    * 'look' command - print the room description
    */
    private void printLook()
    {
        for (Item item : currentRoom.getItemList())
        {
            System.out.println(item.getName());
        }
        System.out.println(currentRoom.getDescription(true));
    }

    /**
    * Walk from room to room
    */
    private void goRoom(Command command)
    {
        if (!command.hasSecondWord())
        {

            /**
            * if the user doesnt type the 2nd word.
            */
            System.out.println("Hmmm.....?");
            return;
        }

        String direction = command.getSecondWord();

        /**
        * If user tries to enter a room through a wall
        */
        Room nextRoom = currentRoom.getExit(direction);
        if (nextRoom == null)
        {
            System.out.println("You bump into the wall, because there is no door there, dooh!");
        }
        else
        {
            currentRoom = nextRoom;
            System.out.println(currentRoom.getShortDescription());
        }
    }

    /**
    * Currentplayer picks up a item.
    */
    private Item pickUpItem(Command command)
    {
        if (!command.hasSecondWord())
        {

            /**
            * if the user doesnt type the 2nd word.
            */
            System.out.println("Take what..?");
            return null;
        }
        String itemName = command.getSecondWord();
        Item pickItem = currentRoom.getItem(itemName);
        if (pickItem == null)
        {
            System.out.println("The item that you require does not exist in this room...");
            return null;
        }
        if (!player.canCarry(pickItem))
        {
            System.out.println("The player can not take the item");
            return null;
        }
        currentRoom.removeItem(itemName);
        player.takeItem(pickItem);
        System.out.println("you have taken the " + itemName);
        return pickItem;
    }

    /**
    * Currentplayer drops a item.
    */
    private void drop(Command command)
    {
        if (!command.hasSecondWord())
        {

            /**
            * if the user doesnt type the 2nd word.
            */
            System.out.println("Drop what..?");
            return;
        }
        String itemName = command.getSecondWord();

        /**
        * If user tries to pick up an item that is not there.
        */
        Item dropItem = player.dropItem(itemName);
        if (dropItem == null)
        {
            System.out.println("The item that you require does not exist in this room...");
        } else
        {
            currentRoom.addItem(dropItem);
            System.out.println("You have droped the " + itemName);
        }
    }

    /**
    * Place a random item in a room.
    */
    private void placeItems()
    {
        ArrayList<Room> roomList = new ArrayList<Room>(rooms.values());
        Random rnd = new Random();
        for (Item item : items.values())
        {
            roomList.get(rnd.nextInt(roomList.size())).addItem(item);
        }
    }
    
    /**
    * Creates a random item for our winning plot. 
    */
    private Item RandomItem()
    {
        int randomIdx = new Random().nextInt(items.size());
        return (Item) items.values().toArray()[randomIdx];
    }

    /**
    * prints out the currentplayers inventory.
    */
    private void printInventory()
    {
        System.out.println(player.getInventory());
    }
    private void addPlayers()
    {
        playersList.add(new Player("Morten", this));
        playersList.add(new Player("Frank", this));
        playersList.add(new Player("Ronni", this));
    }
    public void nextPlayer()
    {
        if (playersList.size() - 1 == playersList.indexOf(player))
        {
            player = playersList.get(0);
        }
        else
        {
            player = playersList.get(playersList.indexOf(player) + 1);
        }
        System.out.println("Next player is : " + player.getName());
    }
}
